/*
 * @Author: XiaoFeng Chen 
 * @Date: 2018-09-28 10:44:40 
 * @Last Modified by: XiaoFeng Chen
 * @Last Modified time: 2018-11-27 13:55:19
 */
//@ts-check
// import { remove as arrayRemove} from '../ext/array';
// import { slice} from '../common/index';

/**
 * 添加鼠标滚轮事件监听
 * @param {Element} elem 事件元素
 * @param {Function} callback 回调函数
 * @param {Boolean} useCapture 是否捕获 
 * @returns {Function} 移除事件监听的函数
 */
export var addWheelListener = (function () {
    var prefix = "", _addEventListener = 'addEventListener', _removeEventListener = 'removeEventListener', support;
    // detect event model
    //  if ( window.addEventListener ) {
    //      _addEventListener =  "addEventListener ";
    //  } else {
    //      _addEventListener =  "attachEvent ";
    //      prefix =  "on ";
    //  }
    // detect available wheel event
    support = "onwheel" in document.createElement("div") ? "wheel" : // Modern browsers support  "wheel "
        //@ts-ignore
        document.onmousewheel !== undefined ? "mousewheel" : // Webkit and IE support at least  "mousewheel "
            "DOMMouseScroll"; // let's assume that remaining browsers are older Firefox

    function _addWheelListener(elem, eventName, callback, useCapture) {
        var backfn = (support == "wheel" ? callback : function (originalEvent) {
            !originalEvent && (originalEvent = window.event);
            // create a normalized event object
            var event = {
                // keep a ref to the original event object
                originalEvent: originalEvent,
                target: originalEvent.target || originalEvent.srcElement,
                type: "wheel",
                deltaMode: originalEvent.type == "MozMousePixelScroll" ? 0 : 1,
                deltaX: 0,
                deltaY: 0,
                deltaZ: 0,
                preventDefault: function () {
                    originalEvent.preventDefault ?
                        originalEvent.preventDefault() :
                        originalEvent.returnValue = false;
                }
            };
            // calculate deltaY (and deltaX) according to the event
            if (support == "mousewheel") {
                event.deltaY = -1 / 40 * originalEvent.wheelDelta;
                // Webkit also support wheelDeltaX
                originalEvent.wheelDeltaX && (event.deltaX = -1 / 40 * originalEvent.wheelDeltaX);
            }
            else {
                event.deltaY = originalEvent.deltaY || originalEvent.detail;
            }
            // it's time to fire the callback
            return callback(event);
        });
        elem[_addEventListener](prefix + eventName, backfn, useCapture || false);
        return function () {
            elem[_removeEventListener](prefix + eventName, backfn, useCapture || false);
        };
    }

    return function (elem, callback, useCapture) {
        // handle MozMousePixelScroll in older Firefox
        if (support == "DOMMouseScroll") {
            return _addWheelListener(elem, "MozMousePixelScroll", callback, useCapture);
        }
        else {
            return _addWheelListener(elem, support, callback, useCapture);
        }
    };
}());

/**
 * 添加窗口resize事件监听
 * @param {Function} fn 回调函数
 * @returns {Function} 移除事件监听
 */
export var addResize = (function () {
    var fns = [];
    var old = window.onresize;
    window.onresize = function () {
        if (old) {
            old.apply(window, slice(arguments));
        }
        fns.forEach((fn) => {
            fn();
        });
    };
    return function (fn) {
        fns.push(fn);
        return function () {
            arrayRemove(fns, fn);
        };
    };
}());

/**
 * 根据事件源决定事件执不执行，事件控制更灵活
 * @param {Element} ignore 忽略的事件源 
 * @param {Function} callback 回调函数
 * @param {String} eventName 事件名
 * @returns {Function} 移除事件监听
 */
export var triggerOnce = function (ignore, callback, eventName = 'click') {
    var temp = function (ev) {
        var isTrigger = true, tar = ev.target;
        if (ignore instanceof Array) {
            ignore.forEach((el) => {
                if (el.contains(tar)) {
                    isTrigger = false;
                }
            })
        } else if (ignore.contains(tar)) {
            isTrigger = false;
        }
        if (isTrigger) {
            callback(ev);
            document.removeEventListener(eventName, temp, true);
        }
    };
    document.addEventListener(eventName, temp, true);
    return function () {
        document.removeEventListener(eventName, temp, true);
    };
};

/**
 * 触发事件 click
 * @param {Element} el 元素
 * @param {String} name 事件名
 */
export var fireEvent = function (el, name) {
    //TODO 只处理了click事件
    if (name === 'click') {
        el['click']();
    } else {
        var event = document.createEvent("Events")
        event.initEvent(name, true, true)
        // event.fireByRxtools = true//签名，标记事件是由avalon触发
        //event.isTrusted = false 设置这个opera会报错
        el.dispatchEvent(event)
    }
}

/**
 * @param {Function} func
 * @param {number} wait
 * @param {boolean} immediate
 * @return {*}
 */
export const debounce = (func, wait, immediate) => {
    let timeout, args, context, timestamp, result

    const later = function () {
        // 据上一次触发时间间隔
        const last = +new Date() - timestamp

        // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
        if (last < wait && last > 0) {
            timeout = setTimeout(later, wait - last)
        } else {
            timeout = null
            // 如果设定为immediate===true，因为开始边界已经调用过了此处无需调用
            if (!immediate) {
                console.log('inner')
                result = func.apply(context, args)
                if (!timeout) context = args = null
            }
        }
    }
    return function (...args) {
        console.log(this, args, 'ags')
        context = this
        timestamp = +new Date()
        const callNow = immediate && !timeout
        // 如果延时不存在，重新设定延时
        if (!timeout) timeout = setTimeout(later, wait)
        if (callNow) {
            result = func.apply(context, args)
            context = args = null
        }
        return result
    }
}
/**
 * 
 * @param {Function} func 
 * @param {Number} delay  执行间隔 固定事件内只执行一次
 * @returns 
 */
export const throttle = (func, delay = 1000) => {
    if (typeof func !== "function") {
        throw new TypeError("Expected a function");
    }
    var prev = Date.now()
    return function () {
        var context = this;
        var args = arguments;
        var now = Date.now();
        if (now - prev >= delay) {
            func.apply(context, args);
            prev = Date.now();
        }
    }
};